/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tpa.TablaPeriodica;

import java.util.Collection;
import java.util.List;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author leandro
 */
@Stateful(mappedName = "TablaPeriodicaSessionBean")
public class TablaPeriodicaSessionBean implements TablaPeriodicaSessionRemote
{

    @PersistenceContext
    private EntityManager entityManager;

    @RolesAllowed("Administrators")
    public Elemento AgregarElemento(Elemento value)
    {
        entityManager.persist(value);
        return entityManager.merge(value);
    }

    @RolesAllowed("Users")
    public Elemento ObtenerElemento(Long numeroAtomico)
    {
        return entityManager.find(Elemento.class, numeroAtomico);
    }

    @RolesAllowed("Users")
    public List ObtenerElementos()
    {
        return entityManager.createQuery("SELECT e FROM Elemento e ORDER BY e.numeroAtomico").getResultList();
    }

    @RolesAllowed("Administrators")
    public void EliminarElemento(Long numeroAtomico)
    {
        entityManager.remove(ObtenerElemento(numeroAtomico));
    }

    @RolesAllowed("Administrators")
    public Clasificacion AgregarClasificacion(Clasificacion clasificacion)
    {
        if (entityManager.contains(clasificacion))
        {
            throw new IllegalArgumentException(clasificacion.toString() + " ya existe.");
        }

        entityManager.persist(clasificacion);
        return entityManager.merge(clasificacion);
    }

    @RolesAllowed("Administrators")
    public SubClase AgregarSubClase(SubClase subclase)
    {
        entityManager.persist(subclase);
        return entityManager.merge(subclase);
    }
    
    @RolesAllowed("Administrators")
    public void EliminarClasificacion(Long id)
    {
        entityManager.remove(this.ObtenerClasificacion(id));
    }

    @RolesAllowed("Users")
    public List ObtenerClasificaciones()
    {
        return entityManager.createQuery("from Clasificacion c ORDER BY c.nombre").getResultList();
    }

    @RolesAllowed("Users")
    public Clasificacion ObtenerClasificacion(Long id)
    {
        return entityManager.find(Clasificacion.class, id);
    }

    @RolesAllowed("Users")
    public List ObtenerSubClases(String nombreClasificacion)
    {
        return entityManager.createQuery("from SubClase s where (:nombre is null or :nombre = '' or s.parentClasificacion.nombre = :nombre) ORDER BY s.parentClasificacion.nombre, s.valor").setParameter("nombre", nombreClasificacion).getResultList();
    }

    @RolesAllowed("Users")
    public Clasificacion ObtenerClasificacion(String nombreClasificacion)
    {
        return (Clasificacion) entityManager.createQuery("from Clasificacion c where c.nombre = :nombre ORDER BY c.nombre").setParameter("nombre", nombreClasificacion).getResultList().get(0);
    }

    @RolesAllowed("Administrators")
    public Clasificacion ActualizarClasificacion(Clasificacion clasificacion)
    {
        return entityManager.merge(clasificacion);
    }

    @RolesAllowed("Administrators")
    public SubClase ActualizarSubClase(SubClase subClase)
    {
        return entityManager.merge(subClase);
    }

    @RolesAllowed("Users")
    public List ObtenerClasificaciones(String nombre, String id)
    {
        int idNumber = (id == null || id.isEmpty()) ? -1 : Integer.parseInt(id);

        return entityManager.createQuery("from Clasificacion c where (:nombre is null or :nombre = '' or c.nombre = :nombre) and (:id < 0 or c.id = id) ORDER BY c.nombre").setParameter("nombre", nombre).setParameter("id", idNumber).getResultList();
    }

    @RolesAllowed("Users")
    public SubClase ObtenerSubClase(Long subClaseId)
    {
        SubClase subclase = entityManager.find(SubClase.class, subClaseId);

        if (subclase != null)
        {
            subclase.getElementos().size();
        }

        return subclase;
    }

    @RolesAllowed("Administrators")
    public void EliminarSubClase(Long subClaseId)
    {
        entityManager.remove(this.ObtenerSubClase(subClaseId));
    }

    @RolesAllowed("Administrators")
    public Elemento ActualizarElemento(Elemento elemento)
    {
        try
        {
            return entityManager.merge(elemento);
        }
        catch (Exception exception)
        {
            return null;
        }
    }

    @RolesAllowed("Administrators")
    public SubClase AgregarSubClase(Long subclaseId, String valor, Long clasificacionId, Long[] elementosElegidos) throws Exception
    {
        try
        {
            Clasificacion clasificacion = this.ObtenerClasificacion(clasificacionId);

            SubClase subclase = null;
            if (subclaseId <= 0L)
            {
                subclase = new SubClase();
                this.AgregarSubClase(subclase);
            }
            else
            {
                subclase = this.ObtenerSubClase(subclaseId);
            }

            subclase.setValor(valor);
            clasificacion.add(subclase);


            while (subclase.getElementos().size() > 0)
            {
                Elemento currentElemento = subclase.getElementos().get(0);
                subclase.remove(currentElemento);
                this.ActualizarElemento(currentElemento);
            }

            for (Long currentElementoId : elementosElegidos)
            {
                Elemento elemento = this.ObtenerElemento(currentElementoId);
                subclase.add(elemento);

                this.ActualizarElemento(elemento);
            }

            return this.ActualizarSubClase(subclase);
        }
        catch (Exception exception)
        {
            throw exception;
        }
    }

    @RolesAllowed("Administrators")
    public Elemento AgregarElemento(Long numeroAtomico, String nombre, String simbolo, Float pesoAtomico, String imageUrl, String infoUrl, Collection<Long> propiedadesId)
    {
        Elemento elemento = null;

        if (numeroAtomico > 0)
        {
            elemento = this.ObtenerElemento(numeroAtomico);
        }

        if (elemento == null)
        {
            elemento = new Elemento();
            elemento.setNumeroAtomico(numeroAtomico);
            this.AgregarElemento(elemento);
        }

        elemento.setNombre(nombre);
        elemento.setSimbolo(simbolo);
        elemento.setPesoAtomico(pesoAtomico);
        elemento.setImageUrl(imageUrl);
        elemento.setInfoUrl(infoUrl);

        for (Long currentPropiedadId : propiedadesId)
        {
            if(currentPropiedadId < 0)
            {
                SubClase currentPropiedad = elemento.getProperty(this.ObtenerClasificacion(-currentPropiedadId).getNombre());

                if(currentPropiedad != null) {
                    elemento.removeProperty(currentPropiedad);
                    this.ActualizarSubClase(currentPropiedad);
                }
            }
            else {
                SubClase currentPropiedad = this.ObtenerSubClase(currentPropiedadId);

                if (currentPropiedad != null)
                {
                    elemento.addProperty(currentPropiedad);
                    this.ActualizarSubClase(currentPropiedad);
                }
            }
        }

        return this.ActualizarElemento(elemento);
    }
}
